
import type { Person1 } from './type'
const p1: Person1 = {
  name: "小明",
  age: 18
}
console.log(p1);

// 类型标注 声明变量指定数据类型
// 常用基本数据类型  
/* let a: number = 10;

a = 20;
a = '你好';
console.log(a); */



/* const a: unknown = [1,2,3,4];
console.log(a.length) */


// const a:never = 'dwdwdw';

// 函数
/* function fn(x: string, y: number):string{
  console.log(x+y);
  return x+y;
}

fn('a',20); */

// 专门定义定义 函数返回值得类型为空 （没有返回值）
/* function fn(x: string, y: number):void{
  console.log(x+y);
  return x+y;
}

fn('a',20); */

/* const fn = (x: number, y: number): number => {
  return x+ y;
} */

// 参数默认值
/* function fn(x: number, y: number, z: number = 100):void{
  console.log(x+y+z);
  
}
fn(10,20) */
// 定义默认值的形参可以不是最后一个 形参嘛？ 可以传实参是 使用undefined占位即可
/* 
function fn(x: number, y: number = 100, z: number):void{
  console.log(x+y+z);
  
}
fn(10, undefined, 30); */

// 可选参数  形参 值 可传可不传
/* function fn(x: number, y: number, z?:number):void{
  console.log(x+y);
}
fn(10, 20) */

// 可选参数 不是最后一个形参嘛  不可以



// object 类型只能标注一个变量是对象，但是对象结构（属性和属性类型）定义 无能为力
/* const p1: object = {
  a: 10,
  b: 20
} */



// interface 接口
/* 
  自定义类型， 一般用来描述对象结构的
*/

/* interface Person {
  name: string;
  age: number;
  gender: number;
}

const p1: Person = {
  name: '小明',
  age: 10,
  gender: 0
} */

// 接口 可选属性
/* interface Person {
  name: string;
  age: number;
  gender?: number;
}

const p1: Person = {
  name: '小明',
  age: 10
} */


// 只读属性
/* interface Person {
  readonly id: number;
  name: string;
  age: number;
  gender?: number;
}

const p1: Person = {
  id: 10,
  name: '小明',
  age: 10,
  gender: 10
}

p1.name = "小红";
p1.id = 23456789;
console.log(p1);
 */

// 接口描述函数 常用语 定义 回调函数的结构


/* interface Func {
  (x:number, y:number): number;
}

function fn(cb: Func){
  cb(10, 20);
}

fn(function(a: number, b: number){
  return a+b;
}) */

// 枚举
/* enum Direction {
  east,
  south,
  west,
  north
} */
// 取值 对象取值
/* console.log(Direction.east);
console.log(Direction.south); */

// 数组形式取值

// console.log(Direction[0]);


// 数字 递增
/* enum Direction {
  east = 6,
  south,
  west,
  north
}
console.log(Direction.south);
 */

// 直接赋非数字的值  下标就没有 无法通过 下标取值
/* enum Direction {
  east = "东",
  south = "南",
  west = "西",
  north = "北"
}

console.log(Direction.east);
 */

/* enum Direction {
  east = 6,
  south,
  west,
  north
}
 */



// 类型推论， 定义变量 形参、返回值 不标注类型， 自动根据 初始值 来推论出类型

// 变量声明 根据 初始值 类型 推论出 变量类型
/* let a = 10;
a = "哈哈哈";
console.log(a);
 */

// 变量定义只声明未赋值 会推论成 any

/* let a;
a = 10;
a ="你好世界";
console.log(a);
 */

// 函数形参 根据 形参默认值 做类型推论 函数返回值类型推论

/* function fn(x: number, b: number, c=10){
  console.log(x, b, c);
  
}

fn(10, 20, "aaaa") */

/* const arr: number[] = [1,2,3,4,5];
// arr.push("你好")
// 使用泛型 定义 数组
const arr2: Array<number> = [1,2,3,4,5];
arr2.push("你好"); */

// 元组 理解为特殊的数组 每个位置 可以存储不同类型的值
/* 
const tuple: [number, string] = [18, 'lin'];

tuple.push(10) */

// const div:HTMLDivElement = document.getElementById('div');
// console.log(div);
 


// 联合类型
/* 
  类型保护 
  当我们一个值 类型为 联合类型，不管使用 联合类型中 任何类型 方法 属性都会报错
  叫做 类型保护

  类型断言
    怎么理解： 相当于 告诉 ts，我确定是这个类型，我使用这个类型api,你别提示了
    使用时注意：
      存在 风险情况下（值还是 你自己传的），使用时建议做一个判断在使用 断言类型的api
*/
/* function fn(a: number|string){
  // console.log(a);
  // console.log(a.toFixed(2));
  // console.log(a.length);
  // 断言语法  值 as 类型;
  const aa = a as string;
  if (aa.length) {
    console.log(aa.length);
    
  } else {
    const b = a as number;
    console.log(b.toFixed(2));
  }
  
}
fn('1.2222') */


// type 类型别名 
/* type User = {name: string;age: number}
const p1: User = {
  name: 'lin',
  age: 18,
} */


// 泛型
/* 
   函数 形参类型 和 返回值类型 一样  （类型还不确定）
*/
function fn<T>(n: T): T{
    return n;
}
fn<number>(100);


const arr: Array<string> = ['a', 'b', 'c'];

arr.push('haha')